package comp6231.project.replica.dimitri;
/**
 * Distributed Retail System
 * Oct 8, 2012 
 */


import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * @author dimitri.tiago
 *
 */
public class CustomerDatabaseInsert implements Runnable
{
	private Semaphore writerSemaphore;
	private RandomAccessCustomerRecord newRecord;
	private String filename;

	public CustomerDatabaseInsert(Semaphore writerSemaphore, RandomAccessCustomerRecord newRecord, String filename)
	{
		this.writerSemaphore = writerSemaphore;
		this.newRecord	     = newRecord;
		this.filename	     = filename;
	}

	@Override
	public void run()
	{
		writerSemaphore.Wait(); // obtain semaphore, entering critical section
								// to ensure atomic insert/update
		try
		{
			// determine if record exists in database
			RandomAccessCustomerRecord oldRecord = selectRecord(newRecord);

			// insert or update record
			if ( ! (oldRecord.getCustomerID().equalsIgnoreCase("")) )
			{
				// update record in database
				updateRecord(oldRecord, newRecord);
			}
			else
			{
				// append new record into database
				RandomAccessFile file = new RandomAccessFile(filename, "rw");

				long appendPosition = file.length();
				file.seek(appendPosition);
				newRecord.write(file);

				System.out.printf(
						"Inserted record (%s, %d, %d) in datatabae.\n", 
						newRecord.getCustomerID(), newRecord.getItemID(), 
						newRecord.getNumberOfItems());
				
				file.close(); // close file
			}	    
		} 
		catch (IOException e)
		{
			e.printStackTrace();
		}

		writerSemaphore.Signal(); 	// release semaphore, exiting critical section
									// allowing next thread to insert/update.			
	}

	private void updateRecord(RandomAccessCustomerRecord oldRecord, RandomAccessCustomerRecord newRecord)
	{	
		try
		{	    
			// find record start position
			long startPosition = findRecStartPosition(oldRecord.getCustomerID(), oldRecord.getItemID());

			// update record in database
			RandomAccessFile file = new RandomAccessFile(filename, "rw");

			file.seek(startPosition);
			int update = oldRecord.getNumberOfItems() + newRecord.getNumberOfItems();
			newRecord.setNumberOfItems(update);
			newRecord.write(file);

			newRecord = selectRecord(oldRecord);
			System.out.printf(
					"Updated record (%s, %d, %d) in datatabasee with (%s %d %d).\n", 
					oldRecord.getCustomerID(), oldRecord.getItemID(), oldRecord.getNumberOfItems(), 
					newRecord.getCustomerID(), newRecord.getItemID(), newRecord.getNumberOfItems());
			
			file.close(); // close file
		} 
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	private RandomAccessCustomerRecord selectRecord(RandomAccessCustomerRecord selectRecord)
	{
		RandomAccessCustomerRecord record = new RandomAccessCustomerRecord();

		try
		{
			RandomAccessFile file = new RandomAccessFile(filename, "r");
			String customerID	  = selectRecord.getCustomerID();
			int itemID		  	  = selectRecord.getItemID();

			while ( ! ((record.getCustomerID().equalsIgnoreCase(customerID)) && (record.getItemID() == itemID)) )
			{
				record.read(file);
			}
			
			file.close(); // close file
		} 
		catch (EOFException eofe )
		{
			// record not found. return empty record
			record = new RandomAccessCustomerRecord();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}

		return record;
	}

	private long findRecStartPosition(String customerID, int itemID)
	{
		long recordStartPosition = 0;

		RandomAccessCustomerRecord record = new RandomAccessCustomerRecord();

		try
		{
			RandomAccessFile file = new RandomAccessFile(filename, "r");

			while ( ! ((record.getCustomerID().equalsIgnoreCase(customerID)) && (record.getItemID() == itemID)) )
			{
				record.read(file);
				recordStartPosition += 20; // count number of records read
			}

			recordStartPosition -= 20; // move to start of record.
			
			file.close();
		} 
		catch (EOFException eofe )
		{
			// record not found.
			recordStartPosition = -1;
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}

		return recordStartPosition;
	}

}
